package com.cloud.easy.im.handler;

import com.cloud.easy.im.argeement.Agreement;
import com.cloud.easy.im.event.ServerEventListener;
import com.cloud.easy.im.handler.disruptor.EventProducer;
import com.cloud.easy.im.handler.strategy.AgreementStrategy;
import com.google.common.collect.Lists;
import io.netty.channel.Channel;

import java.util.List;

/**
 * 消息服务处理基类
 * note：
 * 主要用于策略模式，区分协议类型对应不用的处理器
 *
 * @author wangjian
 * @version 0.1.0
 * @create 2020年09月15日2:16 下午
 */
public abstract class AbstractServerHandler {

    /**
     * io线程执行
     */
    List<AgreementStrategy> strategyList = Lists.newArrayList();

    protected ServerEventListener serverEventListener = null;
    /**
     * 业务线程池
     */
    protected EventProducer eventProducer;

    public AbstractServerHandler() {
    }

    /**
     * 处理接收消息逻辑
     *
     * @param session   channel上下文
     * @param agreement 协议请求体
     */
    public void messageReceived(Channel session, Agreement agreement) throws Exception {
        for (AgreementStrategy strategy : strategyList) {
            if (strategy.algorithmInterface(agreement.getType())) {
                // 消息非业务消息, 交由非业务消息处理器执行如心跳续约处理器
                strategy.handler(session, agreement, serverEventListener);
                return;
            }
        }
        // 消息为业务消息, 交由 EventProducer 线程池异步执行
        eventProducer.onHandler(session, agreement);
    }

    /**
     * 客户端创建链接
     *
     * @param session
     */
    public abstract void sessionCreat(Channel session) throws Exception;

    /**
     * 客户端断开链接
     *
     * @param session
     * @throws Exception
     */
    public abstract void sessionClosed(Channel session) throws Exception;

    /**
     * 异常处理
     *
     * @param session
     * @param cause
     * @throws Exception
     */
    public abstract void exceptionCaught(Channel session, Throwable cause) throws Exception;

    public void setServerEventListener(ServerEventListener serverEventListener) {
        this.serverEventListener = serverEventListener;
    }

    public void setEventProducer(EventProducer eventProducer) {
        this.eventProducer = eventProducer;
    }
}
